﻿using System;
using UnityEngine;
using Random = System.Random;

namespace Core
{
    public static partial class Utils
    {
        /// <summary>
        /// 随机数
        /// </summary>
        public static class Rand
        {
            private static Random mRandom = new();

            public static void InitState(int seed)
            {
                mRandom = new Random(seed);
            }

            public static UInt64 GetUInt64()
            {
                var bytes = new byte[8];
                mRandom.NextBytes(bytes);
                return BitConverter.ToUInt64(bytes, 0);
            }

            public static Int64 GetInt64()
            {
                var bytes = new byte[8];
                mRandom.NextBytes(bytes);
                return BitConverter.ToInt64(bytes, 0);
            }

            /// <summary>
            /// 获取lower与Upper之间的随机数
            /// [lower,upper)
            /// </summary>
            /// <param name="lower"></param>
            /// <param name="upper"></param>
            /// <returns></returns>
            public static int GetNumber(int lower, int upper)
            {
                int value = mRandom.Next(lower, upper);
                return value;
            }

            /// <summary>
            /// 获取lower与Upper之间的随机数
            /// [lower,upper)
            /// </summary>
            /// <param name="lower"></param>
            /// <param name="upper"></param>
            /// <returns></returns>
            public static int Range(int lower, int upper)
            {
                int value = mRandom.Next(lower, upper);
                return value;
            }

            //public static float Range(float lower, float upper)
            //{
            //    float value = m_random.Next(lower, upper);
            //    return value;
            //}


            /// <summary>
            /// 随机Bool值
            /// </summary>
            /// <returns></returns>
            public static bool GetBool()
            {
                int value = mRandom.Next(0, 100);
                return value > 50;
            }

            public static Vector2 GetVector2(float min, float max)
            {
                var x = UnityEngine.Random.Range(min, max);
                var y = UnityEngine.Random.Range(min, max);
                return new Vector2(x, y);
            }
            
            

            /// <summary>
            /// 洗牌，随机打乱数组
            /// </summary>
            /// <param name="arr"></param>
            public static void Shuffle(byte[] arr)
            {
                int n = arr.Length;

                for (int i = 0; i < n; i++)
                {
                    int rand = Range(0, n);

                    (arr[rand], arr[i]) = (arr[i], arr[rand]);
                }
            }

            public static void Shuffle(int[] arr)
            {
                int n = arr.Length;

                for (int i = 0; i < n; i++)
                {
                    int rand = Range(0, n);

                    (arr[rand], arr[i]) = (arr[i], arr[rand]);
                }
            }

            public static void Shuffle<T>(T[] arr)
            {
                int n = arr.Length;

                for (int i = 0; i < n; i++)
                {
                    int rand = Range(0, n);

                    (arr[rand], arr[i]) = (arr[i], arr[rand]);
                }
            }

            public static void Shuffle<T>(System.Collections.Generic.List<T> arr)
            {
                int n = arr.Count;

                for (int i = 0; i < n; i++)
                {
                    int rand = Range(0, n);

                    (arr[rand], arr[i]) = (arr[i], arr[rand]);
                }
            }

            /// <summary>
            /// 从min到max的范围内选取arr.Length个不重复的数字
            /// [min,max)
            /// </summary>
            /// <param name="arr"></param>
            /// <param name="min"></param>
            /// <param name="max"></param>
            public static void Pick(int[] arr, int min, int max)
            {
                if (arr.Length > max - min)
                {
                    return;
                }

                int cnt = 0;

                for (int i = 0; i < arr.Length;)
                {
                    var v = UnityEngine.Random.Range(min, max);
                    if (arr.stl_contains(v, 0, i))
                    {
                        cnt++;
                        if (cnt >= 5)
                        {
                            while (arr.stl_contains(v, 0, i))
                            {
                                v++;
                                if (v >= max)
                                {
                                    v = min;
                                }
                            }

                            cnt = 0;
                            arr[i] = v;
                            i++;
                        }
                    }
                    else
                    {
                        cnt = 0;
                        arr[i] = v;
                        i++;
                    }
                }
            }


            #region 正态分布

            public static float GetNormal()
            {
                float s = 0, u = 0, v;

                while (s > 1 || s == 0)
                {
                    u = mRandom.Next() * 2 - 1;
                    v = mRandom.Next() * 2 - 1;

                    s = u * u + v * v;
                }

                var z = UnityEngine.Mathf.Sqrt(-2 * UnityEngine.Mathf.Log(s) / s) * u;
                return z;
            }

            public static float GetNormal(float miu, float sigma)
            {
                return GetNormal() * sigma + miu;
            }

            #endregion
        }
    }
}